package com.zmn.oms.dubbo.impl.zmn.normal.discount;

import com.zmn.dms.common.enums.coup.ThirdPlatEnum;
import org.apache.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zmn.common.constant.CoupConsts;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.constant.MemberConsts;
import com.zmn.common.dto.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.math.MathUtil;
import com.zmn.common.utils.math.MoneyUtil;
import com.zmn.common.utils.response.ResponseUtil;
import com.zmn.dms.common.dto.coup.dro.CoupConsumeDRO;
import com.zmn.oms.business.interfaces.orderamount.OrderAmountCalcBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.TriggerAmountChangeEnum;
import com.zmn.oms.common.dto.OmsOperator;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.dubbo.dto.common.work.BaseRequestDIO;
import com.zmn.oms.dubbo.dto.zmn.discount.CouponDiscountDIO;
import com.zmn.oms.dubbo.interfaces.zmn.normal.discount.ZsNormalOrderDiscountRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.model.bo.orderamount.OrderAmountCalcBO;
import com.zmn.oms.model.bo.orderamount.ReCalcOrderAmountDIO;
import com.zmn.oms.model.dto.work.modify.amount.DiscountCouponDTO;
import com.zmn.oms.model.dto.work.modify.amount.ZsDiscountCouponDTO;
import com.zmn.oms.model.entity.discount.OrderDiscount;
import com.zmn.oms.model.entity.member.OrderMember;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.vo.work.OperatePermissionVO;
import com.zmn.oms.services.interfaces.discount.OrderDiscountService;
import com.zmn.oms.services.interfaces.member.OrderMemberService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkOperatePermissionBService;
import com.zmn.oms.zmn.normal.business.interfaces.discount.ZsNormalOrderDiscountBService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 类描述：订单优惠
 *
 * @author heciqi
 * @date 2018/12/10 21:31
 */
@Service(loadbalance = "roundrobin", timeout = 5000, retries = 2, version = DubboConsts.INTERFACE_VERSION, validation = "false")
public class ZsNormalOrderDiscountRemoteServiceImpl implements ZsNormalOrderDiscountRemoteService {

	private static final String TAG = "啄木鸟-工单优惠";

	private static final Logger logger = LoggerFactory.getLogger(ZsNormalOrderDiscountRemoteServiceImpl.class);

	@Autowired
	ZsNormalOrderDiscountBService zsNormalOrderDiscountBService;
	@Autowired
	ZsOrderWorkOperatePermissionBService zsOrderWorkOperatePermissionBService;
	@Autowired
	OrderWorkService orderWorkService;
	@Autowired
	OrderMemberService orderMemberService;
	@Autowired
	OrderAmountCalcBService orderAmountCalcBService;
	@Autowired
	OrderDiscountService orderDiscountService;

	@Override
	public ResponseDTO useCoupon(CouponDiscountDIO couponDiscountDIO) {

		// 转换验券平台
		if (Objects.nonNull(couponDiscountDIO.getThirdType()) && !Objects.equals(couponDiscountDIO.getThirdType(), 30)) {
			if (Objects.equals(com.zmn.market.common.enums.ThirdPlatEnum.KOUBEI_PLAT_TYPE.getCode(), couponDiscountDIO.getThirdType())) {
				couponDiscountDIO.setThirdType(ThirdPlatEnum.THIRD_COUP_TYPE_KB.getKey());
			} else if (Objects.equals(com.zmn.market.common.enums.ThirdPlatEnum.MEITUAN_PLAT_TYPE.getCode(), couponDiscountDIO.getThirdType())) {
				couponDiscountDIO.setThirdType(ThirdPlatEnum.THIRD_COUP_TYPE_MT.getKey());
			}
		}

		// 会员权益是否包含限免权益,若包含则不能使用优惠券。
		Long orderId = couponDiscountDIO.getOrderId();
		OrderMember orderMember = orderMemberService.findMemberByKey(orderId);
		logger.info("orderId:{} 开始使用优惠券了哦：{}", orderId, JSON.toJSONString(orderMember));
		if (Objects.nonNull(orderMember) && Objects.equals(orderMember.getEquityType(), MemberConsts.EQUITY_FREE)) {
			return ResponseUtil.responseFail("会员单已使用限免权益，无法与优惠券叠加");
		}

		logger.info("[{}] 使用优惠券：{}", TAG, JSON.toJSONString(couponDiscountDIO));

		String couponCode = couponDiscountDIO.getCouponCode();
		Long workId = couponDiscountDIO.getWorkId();

		if (StringUtils.isBlank(couponCode) || Objects.isNull(orderId) || Objects.isNull(workId)) {
			logger.error("[{}] 参数错误：orderId : {} couponCode : {}", TAG, orderId, couponCode);
			return ResponseUtil.responseFail("提交参数错误");
		}

		// 1、校验优惠券是否可用
		OperatePermissionVO operatePermission = zsOrderWorkOperatePermissionBService.getOperatePermission(couponDiscountDIO.getOrderId(), couponDiscountDIO.getWorkId(), OrderConsts.ORDER_OP_TYPE_DISCOUNT_COUPON);
		if (!operatePermission.getCanOperate()) {
			return ResponseUtil.responseFail(operatePermission.getMsg());
		}

		OrderWork orderWork = orderWorkService.findOrderWorkByKey(couponDiscountDIO.getOrderId(), couponDiscountDIO.getWorkId());
		if (orderWork == null) {
			return ResponseUtil.responseFail("工单不存在");
		}
		boolean canDiscount = false;
		DiscountCouponDTO couponDTO = new DiscountCouponDTO();
		this.setLogParam(couponDiscountDIO, couponDTO);
		couponDTO.setThirdType(couponDiscountDIO.getThirdType());
		// 计算和更新工单金额
		ReCalcOrderAmountDIO calcOrderAmountDIO = orderAmountCalcBService.getReCalcOrderAmountDIO(orderWork);
		calcOrderAmountDIO.setInvoker(2);
		calcOrderAmountDIO.setCouponCode(couponDiscountDIO.getCouponCode());
		calcOrderAmountDIO.setThirdType(couponDiscountDIO.getThirdType());
		try {
			OrderAmountCalcBO orderAmountCalcBO = orderAmountCalcBService.reCalcOrderAmountAndDiscountAmount(TriggerAmountChangeEnum.VALIDATE_COUPON, calcOrderAmountDIO, null);
			if (orderAmountCalcBO.getOrderDiscountCalcBO() != null) {
				List<OrderDiscount> orderDiscountList = orderAmountCalcBO.getOrderDiscountCalcBO().getOrderDiscountList();
				// 外部券
				List<OrderDiscount> couponDiscounts = orderDiscountList.stream()
						.filter(e -> Objects.equals(e.getThirdCode(), GlobalConsts.YES))
						.collect(Collectors.toList());
				if (CollectionUtil.isNotNullOrEmpty(couponDiscounts)) {
					canDiscount = true;
				}
				// 内部券
				else {
					couponDiscounts = orderDiscountList.stream()
							.filter(e -> Objects.equals(e.getRedeemCode(), couponCode))
							.collect(Collectors.toList());
					if (CollectionUtil.isNotNullOrEmpty(couponDiscounts)) {
						canDiscount = true;
					}
				}
				if (canDiscount) {
					OrderDiscount orderDiscount = couponDiscounts.get(0);
					couponDTO.setAmount(orderDiscount.getAmount());
					couponDTO.setItemCode(couponCode);
					couponDTO.setType(orderDiscount.getType());
					couponDTO.setOrderAmountCalcBO(orderAmountCalcBO);
					zsNormalOrderDiscountBService.saveCoupon(couponDTO);
				}
			}
		} catch (OmsBaseException e) {
			Integer thirdPlatEnum = couponDTO.getThirdType() != null ? couponDTO.getThirdType() : ThirdPlatEnum.THIRD_COUP_TYPE_OTHER.getKey();
			couponDTO.setRemark(String.format("%s优惠券：%s，%s",ThirdPlatEnum.getValue(thirdPlatEnum),couponCode,StringUtils.defaultIfBlank(e.getMessage(), "优惠券使用失败-未知原因")));
			zsNormalOrderDiscountBService.saveFailCoupon(couponDTO);
			return ResponseUtil.responseFail(e.getMessage());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return ResponseUtil.responseFail(e.getMessage());
		}

		if (canDiscount) {
			return ResponseUtil.responseSuccess("用券成功，使用1张，总优惠金额 " + MoneyUtil.parseToYuanEndWithUnit(couponDTO.getAmount()));
		} else {
			return ResponseUtil.responseFail("未返回优惠信息");
		}
	}

	/**
	 * 调用 优惠券接口 使用优惠券
	 * @param orderWork
	 * @param couponDiscountDIO
	 * @return
	 */
/*	private ResponseDTO<CoupConsumeDRO> validateCoupon(OrderWork orderWork, CouponDiscountDIO couponDiscountDIO){

		// 入参 couponCode, orderId, userId, amount, cityId, channelId, productId
		String couponCode = couponDiscountDIO.getCouponCode();
		Long orderId = orderWork.getOrderId();
		Long userId = orderWork.getUserId();
		Integer originalAmount = orderWork.getOriginalAmount();
		Integer cityId = orderWork.getCityId();
		Integer channelId = orderWork.getChannelId();
		Integer productId = orderWork.getProductId();
		Integer showProductId = orderWork.getShowProductId();
		Integer masterId = orderWork.getMasterId();

		CoupConsumeDIO coupConsumeDIO = new CoupConsumeDIO();
		coupConsumeDIO.setAmount(originalAmount);
		coupConsumeDIO.setChannelId(channelId);
		coupConsumeDIO.setCityId(cityId);
		coupConsumeDIO.setCode(couponCode);
		coupConsumeDIO.setOrderId(orderId);

		coupConsumeDIO.setMasterId(masterId);
		coupConsumeDIO.setUserId(userId);
		coupConsumeDIO.setProductId(showProductId);

		logger.info("[{}] 使用优惠券接口入参：{}", TAG, JSON.toJSONString(coupConsumeDIO));
		ResponseDTO<CoupConsumeDRO> coupConsumeDROResponseDTO = null;
		try {
			coupConsumeDROResponseDTO = coupRemoteService.receiptConsume(coupConsumeDIO);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return ResponseUtil.responseFail("核销接口调用失败！");
		}
		logger.info("[{}] 使用优惠券接口出参：{}", TAG, JSON.toJSONString(coupConsumeDROResponseDTO));
		return coupConsumeDROResponseDTO;
	}*/

	/**
	 * dto 转换
	 * @param discountCouponDTO
	 * @param data
	 * @return
	 */
	private void convert(OrderWork orderWork, ZsDiscountCouponDTO discountCouponDTO, CoupConsumeDRO data){

		// 优惠类型
		Integer preferentialType = data.getPreferentialType();
		// 优惠值
		Integer preferentialValue = data.getPreferentialValue();

		String couponSourceStr = JSON.toJSONString(data);
		JSONObject couponSourceObj = JSON.parseObject(couponSourceStr);

		// 面值金额
		int facePrice = 0;
		// 售价
		int dealPrice = (int) MathUtil.mul(data.getPrice(), 100);

		// 转换优惠类型
		if (Objects.equals(CoupConsts.PREFERENTIAL_TYPE_DISCOUNT, preferentialType)) {
			// 折扣
			double discountValue = MathUtil.div(100 - preferentialValue, 100, 2);
			facePrice = (int) MathUtil.mul(orderWork.getOriginalAmount(), discountValue);
		} else if (Objects.equals(CoupConsts.PREFERENTIAL_TYPE_REDUCE, preferentialType)) {
			// 立减
			facePrice = preferentialValue;
		}

		// 工单 优惠金额= 面值金额-售价金额
		// 渠道预收=售价金额
		int discountAmount = facePrice - dealPrice;

		discountCouponDTO.setAmount(discountAmount);
		discountCouponDTO.setChannelPrepayAmount(dealPrice);
		discountCouponDTO.setType(OrderConsts.ORDER_DISCOUNT_TYPE_LIMIT_FREE);
		discountCouponDTO.setSourceId(data.getBatchId());
		discountCouponDTO.setSourceData(couponSourceObj.toJSONString());
		discountCouponDTO.setRemark(data.getReceiptCode());
	}

	/**
	 * 设置日志参数
	 * @param dio
	 * @param dto
	 */
	private void setLogParam(BaseRequestDIO dio, OmsOperator dto) {
		dto.setOrderId(dio.getOrderId());
		dto.setWorkId(dio.getWorkId());
		dto.setOperator(dio.getMasterName());
		dto.setOperatorId((long)dio.getMasterId());
		dto.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_MASTER);
		dto.setLongitude(dio.getLongitude());
		dto.setLatitude(dio.getLatitude());
	}
}
